#include <iostream>
#include <map>
#include <string>
#include "MD5.h"
#include "AES.h"
#include "Base64.h"

using namespace std;
using std::string;

void get_rand_str(char s[],int num)
{
    //定义随机生成字符串表
    char *str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    int i,lstr;
    char ss[2] = {0};
    lstr = strlen(str);
    srand((unsigned int)time((time_t *)NULL));//使用系统时间来初始化随机数发生器
    for(i = 1; i <= num; i++){
        sprintf(ss,"%c",str[(rand()%lstr)]);
        strcat(s,ss);//将随机生成的字符串连接到指定数组后面
    }
}

const char g_iv[17] = "";
string EncryptionAES(const string& strSrc, string key) //AES加密
{
    size_t length = strSrc.length();
    int block_num = length / BLOCK_SIZE + 1;
    //明文
    char* szDataIn = new char[block_num * BLOCK_SIZE + 1];
    memset(szDataIn, 0x00, block_num * BLOCK_SIZE + 1);
    strcpy(szDataIn, strSrc.c_str());

    //进行PKCS7Padding填充。
    int k = length % BLOCK_SIZE;
    int j = length / BLOCK_SIZE;
    int padding = BLOCK_SIZE - k;
    for (int i = 0; i < padding; i++)
    {
        szDataIn[j * BLOCK_SIZE + k + i] = padding;
    }
    szDataIn[block_num * BLOCK_SIZE] = '\0';

    //加密后的密文
    char *szDataOut = new char[block_num * BLOCK_SIZE + 1];
    memset(szDataOut, 0, block_num * BLOCK_SIZE + 1);

    //进行进行AES的ECB模式加密
    AES aes;
    aes.MakeKey(key.c_str(), g_iv, 16, 16);
    aes.Encrypt(szDataIn, szDataOut, block_num * BLOCK_SIZE, AES::ECB);
    string str = base64_encode((unsigned char*) szDataOut,
                               block_num * BLOCK_SIZE);
    delete[] szDataIn;
    delete[] szDataOut;
    return str;
}
string DecryptionAES(const string& strSrc, string key) //AES解密
{
    string strData = base64_decode(strSrc);
    size_t length = strData.length();
    //密文
    char *szDataIn = new char[length + 1];
    memcpy(szDataIn, strData.c_str(), length+1);
    //明文
    char *szDataOut = new char[length + 1];
    memcpy(szDataOut, strData.c_str(), length+1);

    //进行AES的ECB模式解密
    AES aes;
    aes.MakeKey(key.c_str(), g_iv, 16, 16);
    aes.Decrypt(szDataIn, szDataOut, length, AES::ECB);

    //去PKCS7Padding填充
    if (0x00 < szDataOut[length - 1] <= 0x16)
    {
        int tmp = szDataOut[length - 1];
        for (int i = length - 1; i >= length - tmp; i--)
        {
            if (szDataOut[i] != tmp)
            {
                memset(szDataOut, 0, length);
                cout << "去填充失败！解密出错！！" << endl;
                break;
            }
            else
                szDataOut[i] = 0;
        }
    }
    string strDest(szDataOut);
    delete[] szDataIn;
    delete[] szDataOut;
    return strDest;
}


int main() {
    std::cout << "Hello, World!" << std::endl;
    string url = "http://119.23.69.24:8170/BusiM/AL001/Check";
    string merchant = "1000022215230183";
    string deviceInfo = "device1";

//    char sn[28] = {0};
//    get_rand_str(sn,28);
//    cout << sn << endl;
    string sn = "LCTeyk1sP0JgxzEC9EH8v2nvRVFs";

//		string keyStr = StrUtil.getRndStr(16);
    string keyStr = "MCxbWcgh4IBa4AIq";

    string totalAmount = "0.01";
    string subject = "通用商户收款";
    string callBack = "http://www.baidu.com";
    string returnURL = "DEFAULT";
    string channel = "ali"; // ali,weixin
    string terminalType = "mobile"; // pc / mobile
    string tradeIP = "119.136.147.33";
    string remark = "buy apple";

    string content = sn + merchant + deviceInfo + totalAmount + subject + callBack + returnURL + channel
                     + terminalType + tradeIP + remark;
    string key = "UVZMMGDM";
    content = content + key;

//    cout << content << endl;
    string _sign = MD5(content).toString();
//    cout << _sign << endl;

    string busiType = "120001";
    string encryptContent = _sign + busiType;
//    cout << "encryptContent : " << encryptContent << endl;
    string encryptData = EncryptionAES(encryptContent, keyStr);
//    cout << "encryptData : " << encryptData << endl;


    return 0;
}